package com.sunnada.edu.system.pub.common;

import org.xvolks.jnative.JNative;
import org.xvolks.jnative.Type;
import org.xvolks.jnative.pointers.Pointer;
import org.xvolks.jnative.pointers.memory.MemoryBlockFactory;
import org.xvolks.jnative.exceptions.NativeException;
import org.xvolks.jnative.pointers.memory.NativeMemoryBlock;

public class MediaInfo {
     
     
     /*通过jnative调用MediaInfo.dll的函数获取媒体文件信息
     *String path为视频文件在硬盘上的全路径。如：F:/1.avi
     *方法返回一个字符串，格式为：播放时长，宽度，高度 */
        
	public static String getVideoInfo(String path) {
		String toDisplay = "";
		MediaInfo mi = null;
    	try {
    		mi = new MediaInfo();
	        if (mi.Open(path) > 0) {
	        	String Time=mi.Get(0, 0, "PlayTime/String3", 1, 0);//获取播放时长 格式为：00：00：00.000
	       
	        	//截去毫秒部分 (.000)
	        	int i=Time.indexOf(".");         
	        	String durationTime=Time.substring(0,i);
	       
	        	String[] Times = durationTime.split(":"); //将截取的时间分割为”时、分、秒“三部分
	       
	        	//将播放时长的时分秒统一换算为秒，并相加，得出最终的播放时长。
	        	String duration=String.valueOf(Integer.parseInt(Times[0])*60*60+Integer.parseInt(Times[1])*60+Integer.parseInt(Times[2]));
	       
	        	//构造格式为：播放时长，宽度，高度 的返回值字符串
	       
	        	toDisplay +=duration;       
	        		toDisplay += ",";
				toDisplay += mi.Get(MediaInfo.Stream_Video, 0, "Width", MediaInfo.Info_Text, MediaInfo.Info_Name);
					toDisplay += ",";
				toDisplay += mi.Get(MediaInfo.Stream_Video, 0, "Height", MediaInfo.Info_Text, MediaInfo.Info_Name);
					toDisplay += ",";
				toDisplay += mi.Get(MediaInfo.Stream_General, 0, "Format", MediaInfo.Info_Text, MediaInfo.Info_Info);
	        }
    	} catch (Exception e) {
    		System.out.println("Exception:" + e.getMessage());
    	} finally {
    		//结束dll调用
    		try {
				mi.Close();
				mi.finalize();
			} catch (HandleNotInitializedException e) {
				e.printStackTrace();
			} catch (NativeException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
			
    	}
    	return toDisplay;
	}   
	
	public static String getAudioInfo(String path) {
		String toDisplay = "";
		MediaInfo mi = null;
    	try {
    		mi = new MediaInfo();
	        if (mi.Open(path) > 0) {
	        	String Time=mi.Get(0, 0, "PlayTime/String3", 1, 0);//获取播放时长 格式为：00：00：00.000
	       
	        	//截去毫秒部分 (.000)
	        	int i=Time.indexOf(".");         
	        	String durationTime=Time.substring(0,i);
	       
	        	String[] Times = durationTime.split(":"); //将截取的时间分割为”时、分、秒“三部分
	       
	        	//将播放时长的时分秒统一换算为秒，并相加，得出最终的播放时长。
	        	String duration=String.valueOf(Integer.parseInt(Times[0])*60*60+Integer.parseInt(Times[1])*60+Integer.parseInt(Times[2]));
	       
	        	//构造格式为：播放时长，宽度，高度 的返回值字符串
	       
	        	toDisplay +=duration;       
	        		toDisplay += ",";
				toDisplay += mi.Get(MediaInfo.Stream_General, 0, "Format", MediaInfo.Info_Text, MediaInfo.Info_Info);
	        }
    	} catch (Exception e) {
    		System.out.println("Exception:" + e.getMessage());
    	} finally {
    		//结束dll调用
    		try {
				mi.Close();
				mi.finalize();
			} catch (HandleNotInitializedException e) {
				e.printStackTrace();
			} catch (NativeException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
			
    	}
    	return toDisplay;
	}
        
        
	public static String getMediaType(String path) {
         
		String toDisplay = "";
         
			try {
                     
                   
            MediaInfo mi = new MediaInfo();
            

        	if (mi.Open(path) > 0) {
          	         
        		toDisplay += mi.Get(MediaInfo.Stream_General, 0, "Format", MediaInfo.Info_Text, MediaInfo.Info_Info);
           
    			//结束dll调用
        		mi.Close();
        		mi.finalize();

        	}
		} catch (Exception e) {
			System.out.println("Exception:" + e.getMessage());
		}                
       	return toDisplay;
	}       
	
	public static String getAudioVideoType(String path) {
		MediaInfo mi = null;
		try {
			mi = new MediaInfo();
			if (mi.Open(path) > 0) {
         		mi.Option("Complete", "1");
         		String text = mi.Inform();				//获取上传上来视频的全部信息
         		//验证文件格式
         		if(text.indexOf("Count of video streams")>=0) {						//不存在要验证的属性，则默认视频格式不正确
         			return Constants.ELEMENT_TYPE1;
         		} else if(text.indexOf("Count of audio streams")>=0) {
         			return Constants.ELEMENT_TYPE5;
         		} else {
         			return null;
         		}
			} else {
				return null;
			}
		} catch (NativeException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
     
	public static String verifyAudioVideoFormat(String path) {
		MediaInfo mi = null;
		try {
			mi = new MediaInfo();
			if (mi.Open(path) > 0) {
         		mi.Option("Complete", "1");
         		String text = mi.Inform();				//获取上传上来视频的全部信息
         		//验证文件格式
         		int s = text.indexOf(MediaInfo.CodecInfoKey);
         		if(s<0) {						//不存在要验证的属性，则默认视频格式不正确
         			return verifyAudioFormat(path);
         		} else {
         			return verifyVideoFormat(mi);
         		}
			} else {
				return "文件解析异常！";
			}
		} catch (NativeException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "文件解析异常！";
	}
	
	public static String verifyAudioFormat(MediaInfo mi) {
		String errMsg = "";
		return errMsg;
	}
	
	public static String verifyAudioFormat(String path) {
		String errMsg = "";
		
		MediaInfo mi = null;
		try {
			mi = new MediaInfo(); //生成上传文件实例
			if (mi.Open(path) > 0) {
				return verifyAudioFormat(mi);
			}
		} catch (NativeException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return errMsg;
	}
     
	private static String verifyVideoFormat(MediaInfo mi) {
		/*try {			//取消上传验证，改为上传完转码
			mi.Option("Complete", "1");
			
     		String text = mi.Inform();				//获取上传上来视频的全部信息
     		String errMsg = "上传的视频格式不是建议的格式，请确认后在上传!";
     		//验证文件格式
     		int s = text.indexOf(MediaInfo.CodecInfoKey);
     		if(s<0) {						//不存在要验证的属性，则默认视频格式不正确
     			return errMsg;
     		}
     		String t = text.substring(s, text.indexOf("\n", s));			//获取当前要验证的字符串
     		
     		if(!"".equals(t.trim())) {			//存在要验证的字符串则继续验证内容是否正确
     			String detail = t.split(":")[1].trim();
     			detail.replace("\r", "");
     			if(!MediaInfo.CodecInfoVal.equals(detail)) {		//与要求不匹配返回
     				return errMsg;
     			}
     		} else {				//不存在要验证的字符串,退出
     			return errMsg;
     		}
     		
     		//验证视频格式
     		s = text.indexOf(MediaInfo.CodecProfileKey);
     		if(s<0) {					//不存在要验证的属性，则默认视频格式不正确
     			return errMsg;
     		}
     		t = text.substring(s, text.indexOf("\n", s));
     		//errMsg = "视频格式必须是\"" + MediaInfo.CodecProfileVal + "@L" + MediaInfo.CodecProfileVersion +  "\"或以下版本，请正确转码！";
     		if(!"".equals(t.trim())) {
     			String detail = t.split(":")[1];			//取出验证的内容  
     			String[] details = detail.split("@");		//由于视频有2个部分要验证 Main@L4.1  故先按照@分割内容
     			if(details.length != 2) {					//如果大小不为2 说明内容不含有@字符 , 直接就不符合格式
     				return errMsg;
     			} else {
     				if(!MediaInfo.CodecProfileVal.equals(details[0].trim())) {			//前面不匹配则退出
     					return errMsg;
     				} else {
     					try {
     						String version = details[1];
     						version = version.replace("\r", "");
     						version =version.replace("L", "");				//去除版本的标志 ,只留版本号
     						double ver = Double.parseDouble(version);
     						if(ver > MediaInfo.CodecProfileVersion || ver <= 0) {			//如果当前版本号不是小于或等于当前版本号则退出
     							return errMsg;
     						}
     					} catch(NumberFormatException e) {			//数字强转失败,说明版本不对,退出
     						return errMsg;
     					}
     				}
     			}
     		} else {				//不存在要验证的字符串,退出
     			return errMsg;
     		}
     		
     		//验证音频格式
     		s = text.indexOf(MediaInfo.CodecIdHintKey);
     		if(s<0) {						//不存在要验证的属性，则默认视频格式不正确
     			return errMsg;
     		}
     		t = text.substring(s, text.indexOf("\n", s));
     		//errMsg = "音频格式不是\"" + MediaInfo.CodecIdHintVal + "\"，请正确转码！";
     		if(!"".equals(t.trim())) {
     			String detail = t.split(":")[1];
     			if(!MediaInfo.CodecIdHintVal.equals(detail.trim())) {
     				return errMsg;
     			}
     		} else {					//不存在要验证的字符串,退出
     			return errMsg;
     		}
     		} catch (HandleNotInitializedException e1) {
				e1.printStackTrace();
			} catch (NativeException e1) {
				e1.printStackTrace();
			} catch (Exception e1) {
				e1.printStackTrace();
			}*/
     		return "";
	}
     /** 20140929 niujs 验证上传的视频是否符合要求
     * @param path
     * @return
     */
	public static String verifyVideoFormat(String path) {
		MediaInfo mi = null;
		try {
			mi = new MediaInfo(); //生成上传文件实例
			if (mi.Open(path) > 0) {
				return verifyVideoFormat(mi);
			}
		} catch (NativeException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}  
        
        
    //以下为jnative封装的调用MediaInfo.dll的函数    
        
        
    final public static int Stream_General       = 0;
    final public static int Stream_Video         = 1;
    final public static int Stream_Audio         = 2;
    final public static int Stream_Text          = 3;
    final public static int Stream_Chapters      = 4;
    final public static int Stream_Image         = 5;
    final public static int Stream_Menu          = 6;
    final public static int Stream_Max           = 7;

    final public static int Info_Name            = 0;
    final public static int Info_Text            = 1;
    final public static int Info_Measure         = 2;
    final public static int Info_Options         = 3;
    final public static int Info_Name_Text       = 4;
    final public static int Info_Measure_Text    = 5;
    final public static int Info_Info            = 6;
    final public static int Info_HowTo           = 7;
    final public static int Info_Max             = 8;
    
    final public static String CodecInfoKey = "Codec/Info";			//要验证文件格式 信息的位置
    final public static String CodecProfileKey = "Codec profile";		//要验证视频格式简介的位置
    final public static String CodecIdHintKey = "Codec ID/Hint";		//要验证音频编码设置id 提示信息的位置
    final public static String CodecInfoVal = "Audio Video Interleave";			//符合要求的文件格式 信息
    final public static String CodecProfileVal = "Main";		//符合要求的视频格式简介
    final public static double CodecProfileVersion = 4.1;		//符合要求的视频格式版本
    final public static String CodecIdHintVal = "MP3";		//符合要求的音频编码设置id 提示信息
    
    final public static String a = "";
    
    private String handle = null;
    private JNative new_jnative;
    private static String libraryName = "";

 
    public MediaInfo() throws NativeException, Exception
    {
        setLibraryName();
        New();
    }

    public MediaInfo(String libraryName) throws NativeException, Exception
    {
        setLibraryName(libraryName);
        New();
    }


   
    private void New() throws NativeException, Exception
    {
        
        new_jnative = new JNative(libraryName, "MediaInfoA_New", true);
        new_jnative.setRetVal(Type.INT);
        new_jnative.invoke();
        handle = new_jnative.getRetVal();
        Option("CharSet", "UTF-8");
    }
      
    public int Open(int begin, int beginSize) throws HandleNotInitializedException, NativeException, Exception
    {
        return Open(begin, beginSize, 0, 0);
    }
    
 
    public int Open(int begin, int beginSize, int end, int endSize) throws HandleNotInitializedException, NativeException, Exception
    {
        if (handle == null)
            throw new HandleNotInitializedException("Handle is not initialized.");

        
        JNative jnative = new JNative(libraryName, "MediaInfoA_Open_Buffer");
        jnative.setRetVal(Type.INT);
        jnative.setParameter(0, Type.INT, handle);
        jnative.setParameter(1, Type.INT, String.valueOf(begin));
        jnative.setParameter(2, Type.INT, String.valueOf(beginSize));
        jnative.setParameter(3, Type.INT, String.valueOf(end));
        jnative.setParameter(4, Type.INT, String.valueOf(endSize));
        jnative.invoke();
        
        
        int ret = Integer.parseInt(jnative.getRetVal());

      
        return ret;
    }

 
    public int Open(String filename) throws HandleNotInitializedException, NativeException, Exception
    {
        if (handle == null)
            throw new HandleNotInitializedException("Handle is not initialized.");

        
        Pointer fileNamePointer = createPointer(filename);


        JNative jnative = new JNative(libraryName, "MediaInfoA_Open");
        jnative.setRetVal(Type.INT);
        jnative.setParameter(0, Type.INT, handle);
        jnative.setParameter(1, fileNamePointer);
        jnative.invoke();

        int ret = Integer.parseInt(jnative.getRetVal());

        fileNamePointer.dispose();

        return ret;
    }


    public String Inform() throws HandleNotInitializedException, NativeException, Exception
    {
        if (handle == null)
            throw new HandleNotInitializedException("Handle is not initialized.");

       
        JNative jnative = new JNative(libraryName, "MediaInfoA_Inform");
        jnative.setRetVal(Type.INT);
        jnative.setParameter(0, Type.INT, handle);
        jnative.setParameter(1, Type.INT, "0"); //Necessary for backward compatibility
        jnative.invoke();

      
        String ret = retrieveString(jnative);

      
        return ret;
    }


     public String Get(int streamKind, int streamNumber, String parameter) throws HandleNotInitializedException, NativeException, Exception
    {
        return Get(streamKind, streamNumber, parameter, MediaInfo.Info_Name, MediaInfo.Info_Text);
    }

 
    public String Get(int streamKind, int streamNumber, String parameter, int infoKind) throws HandleNotInitializedException, NativeException, Exception
    {
        return Get(streamKind, streamNumber, parameter, infoKind, MediaInfo.Info_Name);
    }
    
    
    public String Get(int streamKind, int streamNumber, String parameter, int infoKind, int searchKind) throws HandleNotInitializedException, NativeException, Exception
    {
        if (handle == null)
            throw new HandleNotInitializedException("Handle is not initialized.");

       
        Pointer parameterPointer = createPointer(parameter);

        JNative jnative = new JNative(libraryName, "MediaInfoA_Get");
        jnative.setRetVal(Type.INT);
        jnative.setParameter(0, Type.INT, handle);
        jnative.setParameter(1, Type.INT, String.valueOf(streamKind));
        jnative.setParameter(2, Type.INT, String.valueOf(streamNumber));
        jnative.setParameter(3, parameterPointer);
        jnative.setParameter(4, Type.INT, String.valueOf(infoKind));
        jnative.setParameter(5, Type.INT, String.valueOf(searchKind));
        jnative.invoke();

        String ret = retrieveString(jnative);

        return ret;
    }
    
 
    
    public String Get(int streamKind, int streamNumber, int parameter) throws HandleNotInitializedException, NativeException, Exception
    {
        return Get(streamKind, streamNumber, parameter, MediaInfo.Info_Text);
    }
    
    
  
    public String Get(int streamKind, int streamNumber, int parameter, int infoKind) throws HandleNotInitializedException, NativeException, Exception
    {
        if (handle == null)
            throw new HandleNotInitializedException("Handle is not initialized.");
     

        JNative jnative = new JNative(libraryName, "MediaInfoA_GetI");
        jnative.setRetVal(Type.INT);
        jnative.setParameter(0, Type.INT, handle);
        jnative.setParameter(1, Type.INT, String.valueOf(streamKind));
        jnative.setParameter(2, Type.INT, String.valueOf(streamNumber));
        jnative.setParameter(3, Type.INT, String.valueOf(parameter));
        jnative.setParameter(4, Type.INT, String.valueOf(infoKind));
        jnative.invoke();


        String ret = retrieveString(jnative);

        return ret;
    }
    
      
    public String Option(String option) throws HandleNotInitializedException, NativeException, Exception
    {
        return Option(option, "");
    }
        
   
    public String Option(String option, String value) throws HandleNotInitializedException, NativeException, Exception
    {
        if (handle == null)
            throw new HandleNotInitializedException("Handle is not initialized.");

        Pointer optionPointer = createPointer(option);
        Pointer valuePointer = createPointer(value);

        JNative jnative = new JNative(libraryName, "MediaInfoA_Option");
        jnative.setRetVal(Type.INT);
        jnative.setParameter(0, Type.INT, handle);
        jnative.setParameter(1, optionPointer);
        jnative.setParameter(2, valuePointer);
        jnative.invoke();

        String ret = retrieveString(jnative);
      
        return ret;
    }
    
    static public String Option_Static(String option) throws HandleNotInitializedException, NativeException, Exception
    {
        return Option_Static(option, "");
    }
       
    static public String Option_Static(String option, String value) throws HandleNotInitializedException, NativeException, Exception
    {
        if (libraryName.equals(""))
            setLibraryName();

                Pointer optionPointer = createPointer(option);
        Pointer valuePointer = createPointer(value);

        JNative jnative = new JNative(libraryName, "MediaInfoA_Option");
        jnative.setRetVal(Type.INT);
        jnative.setParameter(0, Type.INT, "0");
        jnative.setParameter(1, optionPointer);
        jnative.setParameter(2, valuePointer);
        jnative.invoke();

       
        String ret = retrieveString(jnative);
     
        return ret;
    }


   
    public int State_Get() throws HandleNotInitializedException, NativeException, Exception
    {
        if (handle == null)
            throw new HandleNotInitializedException("Handle is not initialized.");

       
        JNative jnative = new JNative(libraryName, "MediaInfoA_State_Get");
        jnative.setRetVal(Type.INT);
        jnative.setParameter(0, Type.INT, handle);
        jnative.invoke();

       
        int ret = Integer.parseInt(jnative.getRetVal());     

        return ret;
    }
        
   
    public int Count_Get(int streamKind) throws HandleNotInitializedException, NativeException, Exception
    {
        return Count_Get(streamKind, -1);
    }
  
    public int Count_Get(int streamKind, int streamNumber) throws HandleNotInitializedException, NativeException, Exception
    {
        if (handle == null)
            throw new HandleNotInitializedException("Handle is not initialized.");

        
        JNative jnative = new JNative(libraryName, "MediaInfoA_Count_Get");
        jnative.setRetVal(Type.INT);
        jnative.setParameter(0, Type.INT, handle);
        jnative.setParameter(1, Type.INT, String.valueOf(streamKind));
        jnative.setParameter(2, Type.INT, String.valueOf(streamNumber));
        jnative.invoke();
      
        int retval = Integer.parseInt(jnative.getRetVal());        

        return retval;
    }


    protected void finalize() throws HandleNotInitializedException, NativeException, Exception 
    {
        if (handle == null)
            throw new HandleNotInitializedException("Handle is not initialized.");
      
        JNative jnative = new JNative(libraryName, "MediaInfoA_Delete");
        jnative.setParameter(0, Type.INT, handle);
        jnative.invoke();
     
        jnative.dispose();
       
        new_jnative.dispose();
    }

   
    public void Close() throws HandleNotInitializedException, NativeException, Exception
    {
        if (handle == null)
            throw new HandleNotInitializedException("Handle is not initialized.");
        
        JNative jnative = new JNative(libraryName, "MediaInfoA_Close");
        jnative.setParameter(0, Type.INT, handle);
        jnative.invoke();    
    }


   
    static Pointer createPointer(String value) throws Exception
    {
        value+="\0";
        byte[] array=value.getBytes("UTF-8");
        Pointer valuePointer = new Pointer(MemoryBlockFactory.createMemoryBlock(array.length));
        valuePointer.setMemory(array);
        return valuePointer;
    }

    
    static String retrieveString(JNative jnative) throws Exception
    {
        int address = Integer.parseInt(jnative.getRetVal());
        byte[]  strEnd          ={0};
        int     howFarToSearch  =10000;
        int     length          =0;

        while (true)
        {
            int pos=JNative.searchNativePattern(address+length, strEnd, howFarToSearch);
            if (pos == -1)
                howFarToSearch+=10000; 
            else
            {
                length+=pos;
                break;
            }
        }

        if (length > 0)
        {
            Pointer retPointer = new Pointer(new NativeMemoryBlock(address, length));
            String fileInfo = new String(retPointer.getMemory(), "UTF-8");
            retPointer.dispose();
            return fileInfo;
        }
        else
            return new String();
    }

   
    public static void setLibraryName()
    {
        if (libraryName.equals(""))
        {
            String os=System.getProperty("os.name");
            if (os!=null && os.toLowerCase().startsWith("windows"))
                setLibraryName("MediaInfo.dll");
            else if (os!=null && os.toLowerCase().startsWith("mac"))
                setLibraryName("libmediainfo.dynlib.0");
            else
                setLibraryName("libmediainfo.so.0");
        }
    }
    
  
    public static void setLibraryName(String libName)
    {
        libraryName = libName;
    }
    

    public static void main(String[] args){
    	String tt=getMediaType("D:/Tomcat 5.0/webapps/mMedia/upload/video/201001/res-41-201002011423034370mp4.avi");
    	System.out.println(tt);
    }
        


/**
 * Exception thrown if the handle isn't initialized.
 */
class HandleNotInitializedException extends Exception
{
    HandleNotInitializedException(String msg)
    {
        super(msg);
    }
}
}